<?php

class newMatch {
	private $eventid;
	private $level;
	private $number;
	private $red_teams;
	private $blue_teams;
	private $red_score;
	private $blue_score;
		
	// CONTRACT: __construct : number -> Match
	// PURPOSE
	// __construct is the auto-called function that builds a new Match. It takes a $matchid and returns the Match object for the corresponding match in the database.
	
	function __construct($eventid, $level, $number, $red_teams, $blue_teams, $red_score, $blue_score) {
		$this->eventid 		= $eventid;
		$this->complevel	= $level;
		$this->matchnumber 	= $number;
		$this->red_teams 	= $red_teams;
		$this->blue_teams 	= $blue_teams;
		$this->red_score 	= $red_score;
		$this->blue_score 	= $blue_score;
	}
	
	function getEventID() {
		return $this->eventid;
	}
	function getComplevel() {
		return $this->complevel;
	}
	function getMatchNumber() {
		return $this->matchnumber;
	}
	function getRedScore() {
		return floor($this->red_score);
	}
	function getBlueScore() {
		return floor($this->blue_score);
	}
	function getTeams($color) {
		if ($color == 'red') {
			return $this->red_teams;
		} elseif ($color == 'blue') {
			return $this->blue_teams;
		} else {
			return -1;
		}
	}
	function getTeam($color, $number) {
		$alliance = $this->getTeams($color);
		return $alliance[($number - 1)];
	}
	
	function getEventName() {
		$event = new Event($this->getEventID());
		return $event->getName();
	}
	
	// CONTRACT: getName() : null -> string
	// PURPOSE
	// getName returns a string containing the name of this particular match
	function getName() {
		//import global dictionaries
		global $complevelnames, $complevelshort, $weeknames;
		
		if ($this->complevel == 10) {
			$matchnumber_output = $this->matchnumber;
		}
		
		//echo elim info
		if ($this->complevel > 10) {
			$matchnumber_output = " " . floor($this->matchnumber / 10) . " Match " . ($this->matchnumber - floor($this->matchnumber / 10) * 10);
		}
		
		//correct for database storage technique. Some finals don't have the "1x" they should.
		if ($this->complevel == 50 AND $this->matchnumber < 10) $this->matchnumber+=10;
		if ($this->complevel == 50) {
			$matchnumber_output = " Match " . ($this->matchnumber-10);
		}
		
		//return match name
		return "{$complevelnames[$this->complevel]} {$matchnumber_output}";
	}
	
	function isSane() {
	    if ($this->matchnumber == 0) {
	        return False;
	    }
	    return True;
	}
	
	function insert() {
		mysql_query("INSERT INTO matches (event, complevel, matchnumber, red1, red2, red3, blue1, blue2, blue3, redscore, bluescore) VALUES ('{$this->getEventID()}', '{$this->getComplevel()}', '{$this->getMatchNumber()}', '{$this->getTeam('red', 1)}', '{$this->getTeam('red', 2)}', '{$this->getTeam('red', 3)}', '{$this->getTeam('blue', 1)}', '{$this->getTeam('blue', 2)}', '{$this->getTeam('blue', 3)}', '{$this->getRedScore()}', '{$this->getBlueScore()}')");
		echo "<strong>Match added (complevel: {$this->getComplevel()} - matchnumber: {$this->getMatchnumber()} - event: {$this->getEventID()}).</strong><br />";
	}
	
	function update($matchid) {
		mysql_query("UPDATE matches SET red1='{$this->getTeam('red', 1)}', red2='{$this->getTeam('red', 2)}', red3='{$this->getTeam('red', 3)}', blue1='{$this->getTeam('blue', 1)}', blue2='{$this->getTeam('blue', 2)}', blue3='{$this->getTeam('blue', 3)}', redscore='{$this->getRedScore()}', bluescore='{$this->getBlueScore()}' WHERE event = '{$this->getEventID()}' AND matchnumber = '{$this->getMatchNumber()}' AND complevel = '{$this->getComplevel()}' LIMIT 1");
		echo "<strong>Match updated (complevel: {$this->getComplevel()} - matchnumber: {$this->getMatchnumber()} - event: {$this->getEventID()}).</strong><br />";
	}
}

class adminController {
	// CONTRACT: downloadMatchList : string, number -> bool
	// PURPOSE 
	// downloadMatchList pulls down the HTML match list file from FIRST based on the eventshort and the year and saves it locally.
	function downloadMatchList($eventshort, $eventyear) {	
	    $url = 'http://www2.usfirst.org/' . $eventyear . 'comp/events/' . $eventshort . '/matchresults.html';
		$r = file_get_contents($url);
		
		//open and write contents to file.
		$myFile =  "matches/" . $eventyear . $eventshort . ".html";
		
		if (file_exists($myFile)) {
			unlink($myFile);
		}
		
		$fh = fopen($myFile, 'a') or die("can't open file");
		fwrite($fh, $r);
		fclose($fh);
		echo "Grabbed " . $url . ".</br>"; 
		return TRUE;
	}
	
	// CONTRACT: getMatchList : string, number -> string
	// PURPOSE
	// determines if current matchlist must be redownloaded or not.
	function getMatchList($eventshort, $eventyear) {
	
		//2008 Nationals Overrides. This is so bad.
		switch ($eventshort) {
			case 'arc':
				$eventshort = 'Archimedes';
				break;
			case 'cur':
				$eventshort = 'Curie';
				break;
			case 'gal':
				$eventshort = 'Galileo';
				break;
			case 'new':
				$eventshort = 'Newton';
				break;
			case 'nats':
				$eventshort = 'Einstein';
				break;
		}
	
		$myFile =  "matches/" . $eventyear . $eventshort . ".html";
		//if its the first run
		if (!file_exists($myFile)) {
			echo "Match Listings File Not Found, creating.<br />";
			$this->downloadMatchList($eventshort, $eventyear);
		}
		
		//if the file is over 6 minutes old.
		if ((time() - filemtime($myFile) > 360 AND time() - filectime($myFile) > 0)) {
			echo "Match info is over 6 minutes old. Current age is " . (time() - filemtime($myFile)) . " seconds. Re-downloading current information from FIRST.<br />";
			unlink($myFile);
			$this->downloadMatchList($eventshort, $eventyear);
		}
		return $myFile;
	}
	
	// CONTRACT: logTime : string -> null
	// PURPOSE
	// logTime writes the current time to a file so that we can see when the script ran.
	function logTime($file) {
		$fh = fopen($file, 'a+') or die("can't open file");
		fwrite($fh, "\r\n" . date('l dS \of F Y h:i:s A'));
		fclose($fh);
	}
	
	// CONTRACT : string, number -> List of newMatches
	// PURPOSE
	// getListOfNewMatches takes an Event object and returns a list of newMatches to see if they need to be inserted.
	function getListOfNewMatches($event) {
		$eventid = $event->getEventID();
		$eventshort = $event->getEventShort();
		$eventyear = $event->getYear();
		
		$list_of_new_matches = array();
		$myFile = $this->getMatchList($eventshort, $eventyear);
		$r = file_get_contents($myFile);
		
		//!!strip all linebreaks from the cached data. It creates a problem with MS Word
		//versions of the pages that linebreak in the middle of tags.
		$r = ereg_replace("\n|\r|\r\n|\n\r", "", $r);
		
		$TABLEArray = preg_split ("/<table.*?>/", $r);
		
		/////////////////
		// Do Qualification Matches
		/////////////////
				
		// now try to find which <table> contains the search results are
		// this is to distinguish if a page contains more than one table.
		for($x=0; $x<count($TABLEArray); $x++){
			if(strstr($TABLEArray[$x],"Qualification Matches")){ // the second argument is a string in the table we want to find.
				$resultTable = $x;
			}
		}
		//this code, by Tom Bottiglieri, rips stuff out of FIRST's tables. I love it!
		
		$TRArray = preg_split("/<tr.*?>/i",$TABLEArray[$resultTable]);
		
		$start=3; //3 is the first row of matches, earlier rows are table headers.
		$end = count($TRArray);
		
		//build arrays
		for($i=$start;$i<$end;$i++){
			$TDArray = preg_split ("/<td.*?>/i",$TRArray[$i]);
			
			//col 1 is the time. Eww.
			$complevel = 10;
			$matchnumber = trim(strip_tags($TDArray[2]));
			$red1 = trim(strip_tags($TDArray[3]));
			$red2 = trim(strip_tags($TDArray[4]));
			$red3 = trim(strip_tags($TDArray[5]));
			$blue1 = trim(strip_tags($TDArray[6]));
			$blue2 = trim(strip_tags($TDArray[7]));
			$blue3 = trim(strip_tags($TDArray[8]));
			$redscore = trim(strip_tags($TDArray[9]));
			$bluescore = trim(strip_tags($TDArray[10]));
			
			if (($redscore == "") OR is_null($redscore) OR ($bluescore == "") OR is_null($bluescore)) {
				$redscore = -1;
				$bluescore = -1;
			}
						
			$list_of_new_matches[] = new newMatch($eventid, $complevel, $matchnumber, array($red1, $red2, $red3), array($blue1, $blue2, $blue3), $redscore, $bluescore);
		}
		
		/////////////////
		// Do Elimination Matches
		/////////////////
				
		// now try to find which <table> contains the search results are
		// this is to distinguish if a page contains more than one table.
		for($x=0; $x<count($TABLEArray); $x++){
			if(strstr($TABLEArray[$x],"Elimination Matches")){ // the second argument is a string in the table we want to find.
				$resultTable = $x;
			}
		}
		//this code, by Tom Bottiglieri, rips stuff out of FIRST's tables. I love it!
		
		$TRArray = preg_split("/<tr.*?>/i",$TABLEArray[$resultTable]);
		
		$start=3; //3 is the first row of matches, earlier rows are table headers.
		$end = count($TRArray);
		$counter = 1;
		
		//build arrays
		for($i=$start;$i<$end;$i++){
			$TDArray = preg_split ("/<td.*?>/i",$TRArray[$i]);
			
			//preg_match("/<a.*?<\/a>/",$TDArray[1],$match);
			//$item = strip_tags($match[0]);
			
			//col1 is still the time
			$matchdesc = trim(strip_tags($TDArray[2])); //there is a space at the end.
			//figure out what match it was based on $matchdesc.
			if (is_numeric(strpos($matchdesc, 'Qtr'))) {
				$complevel = 30;
			} else if (is_numeric(strpos($matchdesc, 'Semi'))) {
				$complevel = 40;
			} else if (is_numeric(strpos($matchdesc, 'Final'))) {
				$complevel = 50;
			}
			//pull out the set numbers
			$matchdesc = explode(' ',$matchdesc);
			$matchnum = $matchdesc[1];
			$matchnum = explode('-',$matchnum);
			$matchset = $matchnum[0];
			//and what game in the match?
			$gamenum = $matchnum[1];
			//and put it all together!
			$matchnumber = $matchset * 10 + $gamenum;
			
			//shift up 1 by the name col.
			$red1 = trim(strip_tags($TDArray[4]));
			$red2 = trim(strip_tags($TDArray[5]));
			$red3 = trim(strip_tags($TDArray[6]));
			$blue1 = trim(strip_tags($TDArray[7]));
			$blue2 = trim(strip_tags($TDArray[8]));
			$blue3 = trim(strip_tags($TDArray[9]));
			$redscore = trim(strip_tags($TDArray[10]));
			$bluescore = trim(strip_tags($TDArray[11]));
			
			if (($redscore == 0 AND $bluescore == 0) AND $gamenum > 2) {
				//this is a null match probably.
				if($this->matchCheck($eventid, $matchnumber + 1, $complevel) == TRUE) { //does the NEXT match exist?
					$list_of_new_matches[] = new newMatch($eventid, $complevel, $matchnumber, array($red1, $red2, $red3), array($blue1, $blue2, $blue3), $redscore, $bluescore);
				}
			} else {
				$list_of_new_matches[] = new newMatch($eventid, $complevel, $matchnumber, array($red1, $red2, $red3), array($blue1, $blue2, $blue3), $redscore, $bluescore);
			}
		}
		
		return $list_of_new_matches;
	}
	
	// CONTRACT matchCheck : number, number, number -> boolean
	// PURPOSE
	// matchCheck says whether or not a match already exists in the system. It is primarily used to avoid adding unplayed matches in elims.
	function matchCheck($eventid, $matchnumber, $complevel) {
		if (is_null($matchnumber) or !is_numeric($matchnumber)) {
			echo "Bad Match Number ($matchnumber)<br />";
		} else {
			$match_check_filter = "SELECT * FROM matches WHERE event = '$eventid' AND matchnumber = '$matchnumber' AND complevel = '$complevel'";
			$match_check_query = mysql_query($match_check_filter);			
			if (mysql_num_rows($match_check_query) < 1) {
				return FALSE;
			} else {
				return TRUE;
			}
		}
	}

	// CONTRACT : number -> boolean
	// PURPOSE
	// checkMatchCompletion takes a match and checks if all the data (all teams, both scores) are entered and returns a boolean corresponding to this status
	function checkMatchCompletion($match) {
		if (($match->getTeam('red', 1) > 0) AND
			($match->getTeam('red', 2) > 0) AND
			($match->getTeam('red', 3) > 0) AND
			($match->getTeam('blue', 1) > 0) AND
			($match->getTeam('blue', 2) > 0) AND
			($match->getTeam('blue', 3) > 0) AND
			($match->getRedScore() > -1) AND
			($match->getBlueSCore() > -1)) {
			
			return TRUE;
		} else {
			return FALSE;
		}
	}
}

?>